#include "stdafx.h"
#include "..\headers\State.h"
#include "..\headers\LuaGameObject.h"
#include "..\headers\InputSystem.h"
#include "..\headers\PhysicsWorld.h"
#include "..\headers\LuaEngine.h"
#include "..\headers\Components.h"
#include "..\headers\LuaSystem.h"
#include "..\headers\GameTime.h"
#include "..\headers\GameObjectManager.h"

namespace ne{

State::State(const Ogre::String& name, const Ogre::String& className,Ogre::RenderWindow* renderWindow,InputSystem* inputSystem,LuaEngine* luaEngine,PhysicsWorld* physicsWorld) : 
	m_name(name),
	m_className(className),
	m_inputSystem(inputSystem),
	m_renderWindow(renderWindow),
	m_luaEngine(luaEngine),
	m_physicsWorld(physicsWorld),
	m_gameObjectManager(nullptr),
	m_sceneManager(nullptr){m_viewports.resize(1);}
State::~State(void){}

void State::Enter(){
	//TODO: This entry will have a load content section which will read from a file if the project is not new
	//lua_setglobal();
	//luabind::open(m_luaState);
	
	// If we load the OctreeSceneManager plugin, ST_GENERIC == OctreeSceneManager
	m_sceneManager = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
	m_gameObjectManager = new GameObjectManager;
	m_physicsWorld->InitDebugDraw(m_sceneManager);
	m_physicsWorld->SetDrawDebugData(true);
	m_physicsWorld->SetGameObjectManager(m_gameObjectManager);
	GameObject::SetSceneManager(m_sceneManager);
	ne::LuaSystem::InitState(m_sceneManager,m_gameObjectManager);
	// Game object load section, load LUA script and create objects
	//s_luaEngine->Load(m_filename.c_str());
	Ogre::String luaInit = "state = " + m_className + "()\nstate:onEnter()\n";
	luaL_dostring(m_luaEngine->GetState(), luaInit.c_str());
	// Get first available camera and create a viewport (if one exists)
	if (!m_sceneManager->getCameras().empty()){
		auto it = m_sceneManager->getCameras();
		Ogre::Camera* camera = it.begin()->second;	// get first available camera
		m_viewports.front() = m_renderWindow->addViewport(camera);
		// temp test
		m_viewports.front()->setBackgroundColour(Ogre::ColourValue::Green);
		camera->lookAt(0.0f,0.0f,500.0f);
		// end temp test
	}
	else {
		System::Log("Warning: failed to find a camera when loading state " + m_name);
	}
	System::Msg("Done loading " + m_className);
}

bool State::Update(GameTime* gameTime){
	IComponentUpdate::UpdateAllComponents(gameTime);
	m_gameObjectManager->Update();
#ifdef DEV_MODE
	m_luaEngine->CheckFiles(gameTime);
	if (m_inputSystem->IsKeyDown(OIS::KC_LCONTROL) && m_inputSystem->IsKeyPressed(OIS::KC_N)){
		m_sceneManager->setDisplaySceneNodes(!m_sceneManager->getDisplaySceneNodes());
	}
	if (m_inputSystem->IsKeyDown(OIS::KC_LCONTROL) && m_inputSystem->IsKeyPressed(OIS::KC_B)){
		m_sceneManager->showBoundingBoxes(!m_sceneManager->getShowBoundingBoxes());
	}
	if (m_inputSystem->IsKeyDown(OIS::KC_LCONTROL) && m_inputSystem->IsKeyPressed(OIS::KC_R)){
		this->Restart();
	}
	if (m_inputSystem->IsKeyDown(OIS::KC_LCONTROL) && m_inputSystem->IsKeyDown(OIS::KC_LSHIFT) && m_inputSystem->IsKeyPressed(OIS::KC_D)){
		m_physicsWorld->SetDrawDebugData(!m_physicsWorld->GetDrawDebugData());
	}
	if (m_inputSystem->IsKeyDown(OIS::KC_LCONTROL) && m_inputSystem->IsKeyPressed(OIS::KC_L)){
		lua_gc(m_luaEngine->GetState(),LUA_GCCOLLECT,0);	// force lua garbage collection
	}
#endif
	return true;
}

void State::Exit(){
	m_physicsWorld->Close();
	if (m_gameObjectManager){
		m_gameObjectManager->Shut();
		delete m_gameObjectManager;
		m_gameObjectManager=nullptr;
	}
	Ogre::String luaExit = "state:onExit()\nstate = nil\n";
	luaL_dostring(m_luaEngine->GetState(),luaExit.c_str());
	lua_gc(m_luaEngine->GetState(),LUA_GCCOLLECT,0);	// force lua garbage collection
	m_renderWindow->removeAllViewports();
	if (m_sceneManager){
		Ogre::Root::getSingleton().destroySceneManager(m_sceneManager);
		m_sceneManager = nullptr;
	}
}

void State::Restart(){
	this->Exit();
	this->Enter();
}

}